package com.feng.freader.view.sudo.view;

//import secondriver.sudo.R;
//import secondriver.sudo.bus.Game;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;

import com.feng.freader.R;
import com.feng.freader.view.sudo.bus.Game;

public class NineGridView extends View implements
		DialogInterface.OnClickListener {

	private static final String TAG = "NineGridView";

	public static final int NUM = 3;
	public static final int SIZE = NUM * NUM;
	public static final int ZERO = 0;

	private float gridWidth;
	private float gridHeight;

	private Game game;

	private int backgroundColor = 0xFFFCFCFC;

	private int lightColor = 0xFFFAEBD7;

	private int weightColor = 0xFF000000;

	private int sysTextColor = Color.BLACK;

	private int userTextColor = Color.BLUE;

	private float textHeightRatioInGrid = 0.75F;

	private int touchX;

	private int touchY;

	private Context context;

	private Paint backGroundPaint;

	private Paint lightPaint;

	private Paint darkPaint;

	private Paint numPaint;

	private View dialogView;

	private Integer[] hintNumbers;

	public NineGridView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
		TypedArray typedArray = context.obtainStyledAttributes(attrs,
				R.styleable.NineGridView);

		this.backgroundColor = typedArray.getColor(
				R.styleable.NineGridView_backgroundColor, backgroundColor);
		this.lightColor = typedArray.getColor(
				R.styleable.NineGridView_lightColor, lightColor);
		this.weightColor = typedArray.getColor(
				R.styleable.NineGridView_weightColor, weightColor);
		this.sysTextColor = typedArray.getColor(
				R.styleable.NineGridView_sysTextColor, sysTextColor);

		this.userTextColor = typedArray.getColor(
				R.styleable.NineGridView_userTextColor, userTextColor);

		float defalut = this.textHeightRatioInGrid;
		this.textHeightRatioInGrid = typedArray.getFloat(
				R.styleable.NineGridView_textHeightRatioInGrid,
				textHeightRatioInGrid);
		if (this.textHeightRatioInGrid > 1 || this.textHeightRatioInGrid < 0) {
			this.textHeightRatioInGrid = defalut;
		}
		typedArray.recycle();

		this.initPaint();
	}

	private void initPaint() {
		backGroundPaint = new Paint();
		backGroundPaint.setColor(this.backgroundColor);

		lightPaint = new Paint();
		lightPaint.setColor(this.lightColor);

		darkPaint = new Paint();
		darkPaint.setColor(this.weightColor);

		numPaint = new Paint();
		numPaint.setStyle(Style.STROKE);
		numPaint.setTextAlign(Paint.Align.CENTER);
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		this.gridWidth = w / SIZE * 1.0F;
		this.gridHeight = h / SIZE * 1.0F;
		super.onSizeChanged(w, h, oldw, oldh);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if (null == game) {
			throw new IllegalArgumentException(
					"should call setGame method with current object .");
		}

		canvas.drawRect(0, 0, getWidth(), getHeight(), backGroundPaint);

		for (int i = 1; i < SIZE; i++) {
			canvas.drawLine(0, i * gridHeight, getWidth(), i * gridHeight,
					lightPaint);
			canvas.drawLine(i * gridWidth, 0, i * gridWidth, getHeight(),
					lightPaint);
			if (i % NUM == 0) {
				canvas.drawLine(0, i * gridHeight, getWidth(), i * gridHeight,
						darkPaint);
				canvas.drawLine(i * gridWidth, 0, i * gridWidth, getHeight(),
						darkPaint);
			}
		}

		numPaint.setTextSize(gridHeight * this.textHeightRatioInGrid);
		FontMetrics fm = numPaint.getFontMetrics();
		float offsetX = gridWidth / 2;
		float offsetY = gridHeight / 2 - (fm.ascent + fm.descent) / 2;
		for (int x = 0; x < SIZE; x++) {
			for (int y = 0; y < SIZE; y++) {
				if (!game.isInitialStatusValue(x, y)) {
					numPaint.setColor(this.userTextColor);
				} else {
					numPaint.setColor(this.sysTextColor);
				}
				canvas.drawText(game.getCurrentStatusText(x, y), x * gridWidth
						+ offsetX, y * gridHeight + offsetY, numPaint);
			}
		}
		Log.i(TAG, "onDraw NineGridView.");
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		float px = event.getX();
		float py = event.getY();

		touchX = (int) (px / this.gridWidth);
		touchY = (int) (py / this.gridHeight);

		Log.i(TAG, String.format(
				"onTouch (touchX, touchY, index)=(%d, %d, %d ) ", touchX,
				touchY, (touchY * SIZE + touchX)));

		if (event.getAction() == MotionEvent.ACTION_UP) {

			if (game.isInitialStatusValue(touchX, touchY)) {
				Toast.makeText(context, R.string.alert_cant_modify_toast,
						Toast.LENGTH_SHORT).show();
			} else {
				hintNumbers = getGameHintNumbers(touchX, touchY);
				dialogView = getDialogView(hintNumbers);

				new AlertDialog.Builder(context)
						.setIcon(android.R.drawable.ic_dialog_info)
						.setTitle(R.string.dialog_title)
						.setNegativeButton(android.R.string.cancel, this)
						.setPositiveButton(android.R.string.ok, this)
						.setView(dialogView).show();
			}
		}
		return true;
	}

	private Integer[] getGameHintNumbers(int touchX, int touchY) {

		if (game.isHint()) {
			return game.reCalculateUnUsedNumber(touchX, touchY);
		} else {
			Integer[] hintNumbers = new Integer[SIZE + 1];
			for (int i = 0; i <= SIZE; i++) {
				hintNumbers[i] = i;
			}
			return hintNumbers;
		}
	}

	private View getDialogView(Integer[] hintNumbers) {
		View dialogView = LayoutInflater.from(context).inflate(
				R.layout.dialog_view, null);
		ArrayAdapter<Integer> adapter = new ArrayAdapter<Integer>(context,
				android.R.layout.simple_spinner_item, hintNumbers);
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		final Spinner spinner = (Spinner) dialogView
                .findViewById(R.id.num_spinner);
        spinner.setAdapter(adapter);
		return dialogView;
	}

	@Override
	public void onClick(DialogInterface dialog, int which) {
		if (which == DialogInterface.BUTTON_POSITIVE) {
			Spinner spinner = (Spinner) dialogView
                    .findViewById(R.id.num_spinner);
            Log.i(TAG, "click select number is " + spinner.getSelectedItem());
			Integer num = (Integer) spinner.getSelectedItem();
			drawNewView(touchX, touchY, num);
			if (game.isWon()) {
				Toast.makeText(context, R.string.won_toast, Toast.LENGTH_LONG)
						.show();
				return;
			}
			if (null != hintNumbers && hintNumbers.length == 1
					&& hintNumbers[0] == ZERO) {
				Toast.makeText(context, R.string.alert_toast, Toast.LENGTH_LONG)
						.show();
			}
		}
		if (which == DialogInterface.BUTTON_NEGATIVE) {
			dialog.dismiss();
		}
	}

	private void drawNewView(int touchX, int touchY, Integer num) {
		if (null != num && this.game.isInalidate(touchX, touchY, num)) {
			this.invalidate();
		}
		Log.i(TAG, String.format("refreshView NineGridView on(%d, %d, %d).",
				touchX, touchY, num));
	}

	public void drawSolutionView() {
		game.setCurrentStatusFromOriginalStatus();
		this.invalidate();
	}

	public void drawNewView() {
		game.recoverCurrentStatusFromInitialStatus();
		this.invalidate();
	}

	public void setGame(Game game) {
		this.game = game;
	}

	public Game getGame() {
		return game;
	}

}